import {
  Box3,
  Color,
  DoubleSide,
  Matrix3,
  Mesh,
  MeshBasicMaterial,
  PlaneGeometry,
  RepeatWrapping,
  Scene,
  Shape,
  ShapeGeometry,
  TextureLoader,
  Vector2,
  Vector3,
} from 'three'

// import greenWallTexture from '../../assets/img/green_wall.png'
// import tankWallTexture from '@/assets/img/tank1.png'
import tankWallTexture from '@/assets/img/fourItem.jpg'

const repeatU = 0.1
const repeatV = 0.1

/**
 * 一个用于测试其他功能的test服务而已，无需考虑
 */
export class TestService {
  private _wall1: Mesh | null = null
  private _wall2: Mesh | null = null

  constructor() {}

  public testTextureAlign_wall(scene: Scene) {
    console.log(tankWallTexture)

    // 使用THREE 的plane，生成一个平面作为地板
    const floorGeometry = new PlaneGeometry(50, 50)
    const floorMaterial = new MeshBasicMaterial({ color: 0x8b4513, side: DoubleSide }) // 设置地板材质为棕色
    const floor = new Mesh(floorGeometry, floorMaterial)
    floor.rotation.x = -Math.PI / 2
    scene.add(floor)

    const textureLoader = new TextureLoader()

    const texture1 = textureLoader.load(
      // TODO尝试通过url读取静态文件
      // '../../assets/img/green_wall.png',
      tankWallTexture,
      // onLoad回调
      function (texture) {
        // in this example we create the material when the texture is loaded
        console.log('texture1:', texture)
      },
      // 目前暂不支持onProgress的回调
      undefined,
      // onError回调
      function (err) {
        console.error('An error happened.', err)
      },
    )
    texture1.wrapS = RepeatWrapping
    texture1.wrapT = RepeatWrapping
    // texture1.repeat.set( 4,2 );
    texture1.repeat.set(repeatU, repeatV)

    const texture2 = texture1.clone()
    // 生成一面墙体wall1
    const wWidth: number = 40
    const wHeight: number = 20
    const wallShape1 = new Shape()
    {
      wallShape1.moveTo(0, 0)
      wallShape1.lineTo(0, wHeight)
      wallShape1.lineTo(wWidth, wHeight)
      wallShape1.lineTo(wWidth, 0)
      wallShape1.lineTo(0, 0)
    }
    const wallGeometry = new ShapeGeometry(wallShape1)
    const wallMaterial = new MeshBasicMaterial({ map: texture1, side: DoubleSide })
    const wall1 = new Mesh(wallGeometry, wallMaterial)
    wall1.position.set(-20, 0, 0)
    scene.add(wall1)
    // 额外条件: 注意offsetX = 0.2，也就是纹理图片左移，(0,0)点为(0.2,0)
    // wallMaterial.map?.offset.set(0.2, 0);

    const innerWidth = 16.4
    const innerHeight = 10
    const wallShape2 = new Shape()
    {
      wallShape2.moveTo(0, 0)
      wallShape2.lineTo(0, innerHeight)
      wallShape2.lineTo(innerWidth, innerHeight)
      wallShape2.lineTo(innerWidth, 0)
      wallShape2.lineTo(0, 0)
    }

    // 生成一个额外的墙片wall2，位于wall1的前方
    const wall2Geometry = new ShapeGeometry(wallShape2)
    const wall2Material = new MeshBasicMaterial({ map: texture2, side: DoubleSide })
    wall2Material.color = new Color(0x008c8c)
    wall2Material.transparent = true
    // wall2Material.opacity = 0.8
    const wall2 = new Mesh(wall2Geometry, wall2Material)
    // 将 wall2 放置在 wall1 的前方
    wall2.rotation.y = Math.PI
    wall2.position.set(20, 2, 0.5)
    // wall2.position.x = 8;

    scene.add(wall2)

    console.log('wall1:', wall1)
    console.log('wall2', wall2)
    console.log(scene)

    this._wall1 = wall1
    this._wall2 = wall2

    // this.textureTest()
    this.textureAlign()
  }

  public textureTest() {
    if (!this._wall1 || !this._wall2) {
      return
    }
    const material2 = this._wall2.material as MeshBasicMaterial
    const texture2 = (this._wall2.material as MeshBasicMaterial).map
    // 可知道，wall2旋转了180，offset 0.6是从旋转后的右侧开始的
    // 视觉效果上：未旋转是 正视图是左侧往左偏移0.6， 旋转180后是右侧往右偏移0.6
    // 实际上，都是uv坐标的 + 0.6，因为旋转不改变uv和物体顶点坐标
    if (texture2) {
      texture2?.offset.set(0.6, 0)
      texture2.needsUpdate = true
      material2.needsUpdate = true
    }
  }

  public textureAlign() {
    if (!this._wall1 || !this._wall2) {
      return
    }
    const wallMaterial1 = this._wall1.material as MeshBasicMaterial
    const wallMaterial2 = this._wall2.material as MeshBasicMaterial

    // 直接计算偏移量

    // 假设已经在同一平面, 无需旋转

    // 需要先对齐plane，计算纹理偏移值
    const wall1Box = new Box3().setFromObject(this._wall1)
    const wall2Box = new Box3().setFromObject(this._wall2)

    const baseAlignVector3: Vector3 = wall1Box.min

    const offsetX = wall2Box.min.x - baseAlignVector3.x
    const offsetY = wall2Box.min.y - baseAlignVector3.y

    const offsetU1 = wallMaterial1.map?.offset.x || 0
    const offsetV1 = wallMaterial1.map?.offset.y || 0

    // map.offset 单次重复中的起始偏移量, offset偏移量的值区间 [0, 1.0]
    // 因为repeat的设置，1u = 0.1， 1v = 0.1
    // 偏移量offsetU = (offsetX * 0.1) % 1

    // offsetU = ( offsetX / wallWidth1 * (uvWidth * repeatU) ) % 1
    // 又因为wallWidth1 === uvWidth, 所以可以消去
    let offsetU = (offsetX * repeatU + offsetU1) % 1
    const offsetV = (offsetY * repeatV + offsetV1) % 1

    console.log('offsetXY:')
    console.log(offsetX, offsetY)
    console.log('offsetUV:')
    console.log(offsetU, offsetV)

    if (wallMaterial2.map) {
      // wallMaterial.map.offset.set(offsetU, offsetV)
      const texture2 = wallMaterial2.map
      if (1) {
        const textureRepeatX2: number = texture2.repeat.x

        const uvReverseXMatrix = new Matrix3()
        uvReverseXMatrix.set(-1, 0, 0, 0, 1, 0, 0, 0, 1)
        uvReverseXMatrix.scale(repeatU, repeatV)

        // ∵ 因为wall1和wall2，如果wall2相对wall1是y旋转180°，
        // 物体的顶点坐标和uv坐标不变，但绝对坐标上，他们是相对反着的，

        // ∴ 贴图如果要对应的上，在彼此的绝对uv坐标上，
        // wall1的偏移量offsetU1（左侧）, 对应的就是wall2的偏移量offsetU2 =（wall2整块uv的长度 + offsetU） （右侧）
        const wall2UVLengthX = textureRepeatX2 * (wall2Box.max.x - wall2Box.min.x)
        console.log('before OffsetU', offsetU, 'wall2UVLengthX:', wall2UVLengthX)

        offsetU = (wall2UVLengthX + offsetU) % 1
        uvReverseXMatrix.translate(offsetU, offsetV)

        const v1 = new Vector2(0, 0)
        v1.applyMatrix3(uvReverseXMatrix)
        console.log('[[[wall2 Offset:', offsetU, offsetV)
        console.log('uvReverseXMatrix:', uvReverseXMatrix)
        console.log('vector:', v1)

        texture2.matrix = uvReverseXMatrix
        texture2.matrixAutoUpdate = false // 设置为false，正式启用matrix来对uv坐标进行变换
      }

      texture2.needsUpdate = true
      wallMaterial2.needsUpdate = true
    }
  }
}
